﻿using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using Newtonsoft.Json;
using ZilLion.Service.Core.DapperWrapper;
using ZilLion.Service.Core.Ioc;
using ZilLion.Service.Core.Log;
using ZilLion.Service.Core.Snowflake;
using ZilLion.Service.Core.WebSocket;
using ZilLion.Service.TaskPlatform.Controllers.Websocket;
using ZilLion.Service.TaskPlatform.Domain.Entity;
using ZilLion.Service.TaskPlatform.Domain.Respository.Interface;

namespace ZilLion.Service.TaskPlatform.Controllers.StateContainer
{
    public class TaskRunStateContainer
    {
        private readonly ITaskStateRespository _taskStateRespository;

        public TaskRunStateContainer(ITaskStateRespository taskStateRespository)
        {
            _taskStateRespository = taskStateRespository;

            #region 初始化缓存

            var allNodeTask = taskStateRespository.GetAllTaskState().ToList();

            var nodes =
                from p in allNodeTask
                group p by p.NodeId
                into g
                select g.Key;

            foreach (var node in nodes)
            {
                var statesdic = new ConcurrentDictionary<string, TaskStateEntity>();
                foreach (var state in allNodeTask.Where(x => x.NodeId == node).ToList())
                    statesdic.AddOrUpdate(state.Taskid, state);
                TaskStates.AddOrUpdate(node, statesdic);
            }

            #endregion

            var refreshThread = new Thread(() =>
                {
                    while (true)
                    {
                        Thread.Sleep(3000);
                        FlushStates();
                    }
                    // ReSharper disable once FunctionNeverReturns
                })
                {IsBackground = true};
            refreshThread.SetApartmentState(ApartmentState.MTA);
            refreshThread.Start();
        }

        public ConcurrentDictionary<string, ConcurrentDictionary<string, TaskStateEntity>> TaskStates { get; } =
            new ConcurrentDictionary<string, ConcurrentDictionary<string, TaskStateEntity>>();


        public void FlushStates()
        {
            var states = new List<TaskStateEntity>();
            foreach (var node in TaskStates.Values)
            {
                var statedic = node;
                states.AddRange(statedic.Values);
            }
            try
            {
                using (var unit = new UnitOfWork())
                {
                    foreach (var state in states)
                        _taskStateRespository.SaveTaskExcuteCount(state, unit);
                    unit.Complete();
                }
            }
            catch (Exception e)
            {
                var json = JsonConvert.SerializeObject(states);
                ZilLionLogManager.Instance().Error(e);
                ZilLionLogManager.Instance().Info(json);
            }
        }
    }
}